﻿//ReConnectionSettings.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo
{
	using System;

	using Ecng.Common;

	using StockSharp.BusinessEntities;

	/// <summary>
	/// Настройки механизма отслеживания соединений <see cref="ITrader"/> с торговом системой.
	/// </summary>
	public class ReConnectionSettings
	{
		private readonly Action _exportTimeOutIntervalChanged;

		internal ReConnectionSettings(Action exportTimeOutIntervalChanged)
		{
			if (exportTimeOutIntervalChanged == null)
				throw new ArgumentNullException("exportTimeOutIntervalChanged");

			_exportTimeOutIntervalChanged = exportTimeOutIntervalChanged;

			ConnectingAttemptCount = 0;
			ReConnectingAttemptCount = 100;
			IsReStartExport = false;
			Interval = TimeSpan.FromSeconds(10);
			WorkingTime = new WorkingTime();
			ConnectDisconnectTimeOutInterval = TimeSpan.FromMinutes(1);
		}

		private TimeSpan _interval;

		/// <summary>
		/// Интервал, с которым будут происходить попытки <see cref="ITrader"/> установить соединение с торговой системой.
		/// </summary>
		/// <remarks>
		/// По умолчанию интервал равен 10 секунд.
		/// </remarks>
		public TimeSpan Interval
		{
			get { return _interval; }
			set
			{
				if (value < TimeSpan.Zero)
					throw new ArgumentOutOfRangeException("value", value, "Неподдерживаемое значение.");

				_interval = value;
			}
		}

		private WorkingTime _workingTime;

		/// <summary>
		/// Режим работы, во время которого необходимо производить подключения.
		/// Например, нет необходимости проводить подключение, когда окончены торги на бирже.
		/// </summary>
		public WorkingTime WorkingTime
		{
			get { return _workingTime; }
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				_workingTime = value;
			}
		}

		private int _connectingAttemptCount;

		/// <summary>
		/// Количество попыток установить первоначальное соеднинение, если оно не было установлено (тайм-аут, сетевой сбой и т.д.).
		/// По-умолчанию количество попыток равно 0. Для установление беконечного количества попыток используется значение -1.
		/// </summary>
		public int ConnectingAttemptCount
		{
			get { return _connectingAttemptCount; }
			set
			{
				if (value < -1)
					throw new ArgumentOutOfRangeException("value", value, "Неподдерживаемое значение.");

				_connectingAttemptCount = value;
			}
		}

		private int _reConnectingAttemptCount;

		/// <summary>
		/// Количество попыток переподсоединиться, если соединение было утеряно в процессе работы.
		/// По-умолчанию количество попыток равно 100. Для установление беконечного количества попыток используется значение -1.
		/// </summary>
		public int ReConnectingAttemptCount
		{
			get { return _reConnectingAttemptCount; }
			set
			{
				if (value < -1)
					throw new ArgumentOutOfRangeException("value", value, "Неподдерживаемое значение.");

				_reConnectingAttemptCount = value;
			}
		}

		/// <summary>
		/// Перезапускать ли экспорт после восстановления соединения или при тайм-ауте поступления данных.
		/// По-умолчанию режим выключен.
		/// </summary>
		public bool IsReStartExport { get; set; }

		private TimeSpan _connectDisconnectTimeOutInterval;

		/// <summary>
		/// Время ожидания события успешного подключения/отключения. По-умолчанию значение равно 1 минуте.
		/// Если значение равно <see cref="TimeSpan.Zero"/>, то мониторинг не производится.
		/// </summary>
		public TimeSpan ConnectDisconnectTimeOutInterval
		{
			get { return _connectDisconnectTimeOutInterval; }
			set
			{
				if (value < TimeSpan.Zero)
					throw new ArgumentOutOfRangeException("value", value, "Неподдерживаемое значение.");

				_connectDisconnectTimeOutInterval = value;
			}
		}

		private TimeSpan _exportTimeOutInterval;

		/// <summary>
		/// Интервал для мониторинга потери передачи данных между роботом и торговой программой.
		/// </summary>
		/// <remarks>
		/// Если мониторинг уже был установлен до этого, то применяется новое значение для интервала.
		/// Если значение равно <see cref="TimeSpan.Zero"/>, то мониторинг останавливается.
		/// По-умолчанию мониторинг выключен.
		/// </remarks>
		public TimeSpan ExportTimeOutInterval
		{
			get { return _exportTimeOutInterval; }
			set
			{
				if (value < TimeSpan.Zero)
					throw new ArgumentOutOfRangeException("value", value, "Неподдерживаемое значение.");

				if (_exportTimeOutInterval != value)
				{
					_exportTimeOutInterval = value;
					_exportTimeOutIntervalChanged();	
				}
			}
		}

		/// <summary>
		/// Событие об успешном восстановлении соединения.
		/// </summary>
		public event Action ConnectionRestored;

		/// <summary>
		/// Событие об ошибке при попытке восстановить соединение.
		/// Возникает каждый раз при неудачной попытке восстановления соединения.
		/// </summary>
		public event Action<Exception> ConnectionAttemptError;

		/// <summary>
		/// Событие о тайм-ауте поступающих данных в программу. Событие позволяет узнать, как долго торговая программа не посылала данные роботу.
		/// Подобное событие сигнализирует о сбое передачи данных между роботом и торговой программой.
		/// </summary>
		public event Action ExportTimeOut;

		internal void RaiseConnectionRestored()
		{
			ConnectionRestored.SafeInvoke();
		}

		internal void RaiseConnectionAttemptError(Exception error)
		{
			ConnectionAttemptError.SafeInvoke(error);
		}

		internal void RaiseExportTimeOut()
		{
			ExportTimeOut.SafeInvoke();
		}
	}
}